package com.dabai.iot.core.utils;

import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.dabai.iot.common.enums.AlarmConditionEnum;
import com.dabai.iot.common.constant.IotKeyConstant;
import com.dabai.iot.core.model.AlarmCheckResult;
import com.dabai.iot.core.model.AlarmTriggeredCondition;
import com.dabai.iot.core.model.AlarmTriggeredParameter;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 告警配置触发条件检查器
 * 用于根据设备上报的数据和预设的告警条件进行比对，判断是否触发告警并返回详细的触发条件信息
 *
 * @author kev1n
 */
public class AlarmChecker {

    public static AlarmCheckResult checkAlarm(AlarmConditionEnum conditionEnum, String reportValue, String alarmConditionsJson) {
        JSONArray conditions = JSONArray.parseArray(alarmConditionsJson);

        if (AlarmConditionEnum.STATUS.equals(conditionEnum)) {
            return checkDeviceStatusCondition(reportValue, conditions);
        } else {
            return checkPropertyConditions(reportValue, conditions);
        }
    }

    public static AlarmCheckResult checkPropertyConditions(String propertyPayload, JSONArray conditions) {
        JSONObject reportPayloadJson = JSONObject.parseObject(propertyPayload);
        // 解析设备上报数据为内部使用的 Map 结构
        Map<String, Map<String, Object>> reportPropertiesMap = parsePayloadJson(reportPayloadJson);

        // 存储所有触发的条件
        List<AlarmTriggeredCondition> triggeredConditions = new ArrayList<>();

        // 遍历所有条件，检查是否满足
        for (int i = 0; i < conditions.size(); i++) {
            JSONObject condition = conditions.getJSONObject(i);

            // 找出其中的属性条件
            if (AlarmConditionEnum.PROPERTY.getValue().equals(condition.getString("type"))) {
                JSONArray conditionParameters = condition.getJSONArray("parameters");
                if (checkPropertyParameters(conditionParameters, reportPropertiesMap)) {
                    // 如果条件满足，创建触发条件对象并记录详细信息
                    AlarmTriggeredCondition triggeredCondition = new AlarmTriggeredCondition();
                    triggeredCondition.setConditionEnum(AlarmConditionEnum.PROPERTY);

                    List<AlarmTriggeredParameter> triggeredParameters = new ArrayList<>();
                    JSONArray params = condition.getJSONArray("parameters");
                    for (int j = 0; j < params.size(); j++) {
                        JSONObject param = params.getJSONObject(j);
                        AlarmTriggeredParameter triggeredParam = new AlarmTriggeredParameter();
                        // 记录参数的基本信息
                        triggeredParam.setBlockIdentifier(param.getString("blockIdentifier"));
                        triggeredParam.setPropertyIdentifier(param.getString("identifier"));
                        triggeredParam.setComparator(param.getString("comparator"));
                        triggeredParam.setConditionValue(param.getString("value"));

                        // 获取并记录设备上报的实际值
                        Map<String, Object> blockProps = reportPropertiesMap.getOrDefault(
                            param.getString("blockIdentifier"), new HashMap<>());
                        triggeredParam.setReportValue(blockProps.getOrDefault(
                            param.getString("identifier"), "unknown").toString());

                        triggeredParameters.add(triggeredParam);
                    }
                    triggeredCondition.setParameters(triggeredParameters);

                    triggeredConditions.add(triggeredCondition);
                }
            }
        }

        // 返回检查结果，包含是否触发告警和触发的条件列表
        return new AlarmCheckResult(!triggeredConditions.isEmpty(), triggeredConditions);
    }

    /**
     * 解析设备上报的属性 JSON 数据，转换为内部使用的 Map 结构
     *
     * @param payloadJson 设备数据的JSON对象
     * @return 返回以块标识符 blockIdentifier 为键，属性 Map 为值的嵌套 Map 结构
     */
    private static Map<String, Map<String, Object>> parsePayloadJson(JSONObject payloadJson) {
        Map<String, Map<String, Object>> propertiesMap = new HashMap<>();
        JSONArray blocks = payloadJson.getJSONArray(IotKeyConstant.BLOCKS);
        if (blocks != null) {
            for (int i = 0; i < blocks.size(); i++) {
                JSONObject block = blocks.getJSONObject(i);
                String blockIdentifier = block.getString(IotKeyConstant.BLOCK_ID);
                JSONObject properties = block.getJSONObject(IotKeyConstant.PROPERTIES);

                Map<String, Object> blockProperties = new HashMap<>();
                if (properties != null) {
                    blockProperties.putAll(properties);
                }
                propertiesMap.put(blockIdentifier, blockProperties);
            }
        }
        return propertiesMap;
    }

    /**
     * 检查一个属性类型的告警条件的全部参数
     * 对于属性条件，一个 condition 所有参数必须都满足才认为条件满足
     *
     * @param conditionParameters 属性条件的参数列表
     * @param reportPropertiesMap 设备上报属性的 Map 结构
     * @return 如果所有参数都满足返回true，否则返回false
     */
    private static boolean checkPropertyParameters(JSONArray conditionParameters, Map<String, Map<String, Object>> reportPropertiesMap) {
        for (int i = 0; i < conditionParameters.size(); i++) {
            JSONObject param = conditionParameters.getJSONObject(i);
            String blockIdentifier = param.getString("blockIdentifier");
            String identifier = param.getString("identifier");
            String dataType = param.getString("dataType");
            int comparator = param.getIntValue("comparator");
            String conditionValue = param.getString("value");

            // 获取设备上报的实际值
            Map<String, Object> blockProps = reportPropertiesMap.getOrDefault(blockIdentifier, new HashMap<>());
            Object reportValue = blockProps.get(identifier);

            // 如果上报值不存在，条件不满足
            if (reportValue == null) {
                return false;
            }

            // 类型转换
            Object convertedConditionValue = TslUtil.convertValue(conditionValue, dataType);
            Object convertedReportValue = TslUtil.convertValue(reportValue.toString(), dataType);

            // 比较
            if (!compareValues(convertedReportValue, convertedConditionValue, comparator)) {
                return false; // 只要有一个参数不满足，整个条件就不满足
            }
        }

        return true; // 所有参数都满足
    }

    /**
     * 根据数据类型转换值
     *
     * @param value    要转换的值
     * @param dataType 数据类型（Int, Float, Bool, String）
     * @return 转换后的值
     */
    @Deprecated
    private static Object convertValue(String value, String dataType) {
        try {
            return switch (dataType.toLowerCase()) {
                case "int32" -> Integer.parseInt(value);
                case "float" -> Float.parseFloat(value);
                case "bool" -> Boolean.parseBoolean(value);
                default -> value; // 默认按字符串处理
            };
        } catch (NumberFormatException e) {
            return null; // 转换失败
        }
    }

    /**
     * 比较值
     * <p>
     * 比较符映射：1: >   2: >=   3: <   4: <=  5: ==  6: !=  7: contains  8: !contains
     * 数值类型：支持 1-6 比较符
     * 布尔类型：支持 5、6 比较符
     * 字符串类型：支持 5-8 比较符
     */
    private static boolean compareValues(Object reportValue, Object conditionValue, int comparator) {
        if (reportValue instanceof Number && conditionValue instanceof Number) { // 数字类型的比较

            // 数值类型统一转为 Double 比较
            double reportNum = ((Number) reportValue).doubleValue();
            double conditionNum = ((Number) conditionValue).doubleValue();

            return switch (comparator) {
                case 1 -> reportNum > conditionNum;  // 大于
                case 2 -> reportNum >= conditionNum; // 大于等于
                case 3 -> reportNum < conditionNum;  // 小于
                case 4 -> reportNum <= conditionNum; // 小于等于
                case 5 -> reportNum == conditionNum; // 等于
                case 6 -> reportNum != conditionNum; // 不等于
                default -> false; // 未知比较器
            };
        } else if (reportValue instanceof String reportStr && conditionValue instanceof String conditionStr) { // 字符串类型的比较

            return switch (comparator) {
                case 5 -> reportStr.equals(conditionStr);    // 等于
                case 6 -> !reportStr.equals(conditionStr);   // 不等于
                case 7 -> reportStr.contains(conditionStr);  // 包含
                case 8 -> !reportStr.contains(conditionStr); // 不包含
                default -> false; // 未知比较器
            };
        } else if (reportValue instanceof Boolean && conditionValue instanceof Boolean) { // 布尔类型的比较

            boolean reportBool = (Boolean) reportValue;
            boolean conditionBool = (Boolean) conditionValue;

            return switch (comparator) {
                case 5 -> reportBool == conditionBool; // 等于
                case 6 -> reportBool != conditionBool; // 不等于
                default -> false; // 未知比较器
            };
        }

        return false; // 类型不匹配或未知比较器
    }

    /**
     * 检查设备状态条件
     *
     * @param reportStatus 设备状态
     * @param conditions   告警条件
     * @return 如果设备状态匹配返回true，否则返回false
     */
    private static AlarmCheckResult checkDeviceStatusCondition(String reportStatus, JSONArray conditions) {
        // 存储所有触发的条件
        List<AlarmTriggeredCondition> triggeredConditions = new ArrayList<>();

        // 遍历所有条件，检查是否满足
        for (int i = 0; i < conditions.size(); i++) {
            JSONObject conditionJson = conditions.getJSONObject(i);

            String type = conditionJson.getString("type");
            if (AlarmConditionEnum.STATUS.getValue().equals(type)) {
                String conditionValue = conditionJson.getString("value");
                if (reportStatus.equals(conditionValue)) {
                    AlarmTriggeredCondition triggeredCondition = new AlarmTriggeredCondition();
                    triggeredCondition.setConditionEnum(AlarmConditionEnum.STATUS);
                    triggeredCondition.setDeviceStatus(reportStatus);

                    triggeredConditions.add(triggeredCondition);
                }
            }
        }
        return new AlarmCheckResult(!triggeredConditions.isEmpty(), triggeredConditions);
    }

}
